package moodish.dummy;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.LinkedList;

import moodish.comm.ServerMessage;
import moodish.comm.ClientMessage;
import moodish.comm.ServerSideMessage.Type;

/**
 * The Class DealWithServer.
 */
public class DealWithServer {

	/** The client comm dummy. */
	private ClientCommDummy clientCommDummy;

	/** The thread list. */
	private LinkedList<Thread> threadList;

	/** The input stream. */
	private ObjectInputStream in;

	/** The output stream. */
	private ObjectOutputStream out;

	/**
	 * InnerClass MessageSender that is used for transmitting messages that are
	 * in the SendMessageList. When a ServerMessage with CLIENT_DISCONNECTED
	 * type is received, the output stream is closed and the threads responsible
	 * for receiving and sending messages are interrupted.
	 * 
	 */
	private class MessageSender extends Thread {

		@Override
		public void run() {
			while (!interrupted()) {
				try {
					ServerMessage sm = clientCommDummy.getSendMessageList()
							.take();
					out.writeObject(sm);
					if (sm.getType() == Type.CLIENT_DISCONNECTED) {
						out.close();
						interruptThreads();
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

	}

	/**
	 * InnerClass MessageReceiver that is used for receiving messages and put
	 * them in the ReceiverMessageList.
	 * 
	 */
	private class MessageReceiver extends Thread {
		@Override
		public void run() {
			while (!interrupted()) {
				try {
					ClientMessage cm = (ClientMessage) in.readObject();
					clientCommDummy.getReceiveMessageList().add(cm);
				} catch (ClassNotFoundException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}

			}
		}
	}

	/**
	 * Instantiates a new deal with server.
	 * 
	 * @param socket
	 *            the socket for the client
	 * @param nickname
	 *            the nickname of the client
	 * @param clientCommDummy
	 *            the client comm dummy of the client
	 *            
	 * The constructor also creates the Threads responsible for receiving and sending 
	 * messages to and for the client and starting them.
	 * 
	 *  
	 * 
	 *            
	 */
	public DealWithServer(Socket socket, String nickname,
			ClientCommDummy clientCommDummy) {
		this.clientCommDummy = clientCommDummy;
		try {
			threadList = new LinkedList<Thread>();
			out = new ObjectOutputStream(socket.getOutputStream());
			in = new ObjectInputStream(socket.getInputStream());

			clientCommDummy.getSendMessageList().add(
					new ServerMessage(Type.CLIENT_CONNECTED, null, nickname));

			threadList.add(new MessageReceiver());
			threadList.add(new MessageSender());
			startThreads();

		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Start threads.
	 */
	private void startThreads() {
		for (Thread t : threadList) {
			t.start();
		}
	}

	/**
	 * Interrupt threads.
	 */
	private void interruptThreads() {
		for (Thread t : threadList) {
			t.interrupt();
		}
	}

}
